package com.shycloud.mido.common.pay.iospay.utils;

import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.shycloud.mido.common.core.constant.CommonConstants;
import com.shycloud.mido.common.core.exception.BusinessException;
import com.shycloud.mido.common.core.util.R;
import java.io.ByteArrayInputStream;
import java.security.PublicKey;
import java.security.cert.CertificateFactory;
import java.security.interfaces.ECPublicKey;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import javax.net.ssl.*;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Locale;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;

/**
 * ios 支付工具类
 *
 * @author nianhua.jiang
 * @date 2020/8/10
 */
public class IosPayUtils {

	/** 自动续费 productId */
	public static final String VIP_AUTO_PAY = "VIP_month_autonew";
	/** 沙箱环境地址 */
	private static final String URL_SANDBOX = "https://sandbox.itunes.apple.com/verifyReceipt";
	/** 正式环境地址 */
	private static final String URL_VERIFY = "https://buy.itunes.apple.com/verifyReceipt";

	private static class TrustAnyTrustManager implements X509TrustManager {

		@Override
		public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
		}

		@Override
		public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
		}

		@Override
		public X509Certificate[] getAcceptedIssuers() {
			return new X509Certificate[]{};
		}
	}

	private static class TrustAnyHostnameVerifier implements HostnameVerifier {

		@Override
		public boolean verify(String hostname, SSLSession session) {
			return true;
		}
	}


	/**
	 * 苹果服务器验证
	 *
	 * @param receipt
	 * @param type
	 * @return java.lang.String
	 * @author nianhua.jiang
	 * @date 2020/8/10 14:52
	 */
	public static String buyAppVerify(String receipt, int type) {

		//环境判断 线上/开发环境用不同的请求链接
		String url = "";
		if (type == 0) {
			//沙盒测试
			url = URL_SANDBOX;
		} else {
			//线上测试
			url = URL_VERIFY;
		}

		try {
			SSLContext sc = SSLContext.getInstance("SSL");
			sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new java.security.SecureRandom());
			URL console = new URL(url);
			HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
			conn.setSSLSocketFactory(sc.getSocketFactory());
			conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
			conn.setRequestMethod("POST");
			conn.setRequestProperty("content-type", "text/json");
			conn.setRequestProperty("Proxy-Connection", "Keep-Alive");
			conn.setDoInput(true);
			conn.setDoOutput(true);
			BufferedOutputStream hurlBufOus = new BufferedOutputStream(conn.getOutputStream());
			//拼成固定的格式传给平台
			String str = String.format(Locale.CHINA, "{\"receipt-data\":\"" + receipt + "\"}");
			hurlBufOus.write(str.getBytes());
			hurlBufOus.flush();

			InputStream is = conn.getInputStream();
			BufferedReader reader = new BufferedReader(new InputStreamReader(is));
			String line = null;
			StringBuffer sb = new StringBuffer();
			while ((line = reader.readLine()) != null) {
				sb.append(line);
			}

			return sb.toString();
		} catch (Exception ex) {
			System.out.println("苹果服务器异常");
			throw new BusinessException(new R(CommonConstants.FAIL_BOARD, "苹果服务器异常标识", false));
		}

	}

	/**
	 * 苹果服务器验证(自动续费)
	 *
	 * @param receipt
	 * @param type
	 * @return java.lang.String
	 * @author nianhua.jiang
	 * @date 2020/8/10 14:52
	 */
	public static String buyAppVerifyAuto(String receipt, int type, String shareSecret) {

		BufferedReader in = null;

		//环境判断 线上/开发环境用不同的请求链接
		String url = "";
		if (type == 0) {
			//沙盒测试
			url = URL_SANDBOX;
		} else {
			//线上测试
			url = URL_VERIFY;
		}

		try {
			//请求参数
			HttpClient httpclient = HttpClientBuilder.create().useSystemProperties().build();
			HttpPost httpPost = new HttpPost(url);
			httpPost.setHeader("content-type", "text/json");
			httpPost.setHeader("Proxy-Connection", "Keep-Alive");
			StringEntity entity = new StringEntity(
					"{\"receipt-data\":\"" + receipt + "\"" + "," + "\"password\":\"" + shareSecret + "\"}", "UTF-8");
			httpPost.setEntity(entity);

			//设置超时时间
			RequestConfig requestConfig = RequestConfig.custom()
					.setConnectTimeout(100000).setConnectionRequestTimeout(100000)
					.setSocketTimeout(100000).build();
			httpPost.setConfig(requestConfig);

			HttpResponse response = httpclient.execute(httpPost);
			int code = response.getStatusLine().getStatusCode();
			if (code == 200) {
				in = new BufferedReader(new InputStreamReader(response.getEntity()
						.getContent(), "utf-8"));
				StringBuffer sb = new StringBuffer("");
				String line = "";
				String NL = System.getProperty("line.separator");
				while ((line = in.readLine()) != null) {
					sb.append(line + NL);
				}
				in.close();
				return sb.toString();
			} else {
				System.out.println("状态码：" + code);
				return null;
			}

//			SSLContext sc = SSLContext.getInstance("SSL");
//			sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new java.security.SecureRandom());
//			URL console = new URL(url);
//			HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
//			conn.setSSLSocketFactory(sc.getSocketFactory());
//			conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
//			conn.setRequestMethod("POST");
//			conn.setRequestProperty("content-type", "text/json");
//			conn.setRequestProperty("Proxy-Connection", "Keep-Alive");
//			conn.setDoInput(true);
//			conn.setDoOutput(true);
//			BufferedOutputStream hurlBufOus = new BufferedOutputStream(conn.getOutputStream());
//			//TODO 拼成固定的格式传给平台
//			String str = String
//					.format(Locale.CHINA, "{\"receipt-data\":\"" + receipt + "\"" + "," + "\"password\":\"" + shareSecret + "\"}");
//			hurlBufOus.write(str.getBytes());
//			hurlBufOus.flush();
//
//			InputStream is = conn.getInputStream();
//			BufferedReader reader = new BufferedReader(new InputStreamReader(is));
//			String line = null;
//			StringBuffer sb = new StringBuffer();
//			while ((line = reader.readLine()) != null) {
//				sb.append(line);
//			}
//			return sb.toString();
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new BusinessException(ex.getMessage());
		}

	}

	public static void verify(String jwt) throws CertificateException {
		// 拿到 header 中 x5c 数组中第一个
		DecodedJWT decodedJWT = JWT.decode(jwt);
		String payload = new String(java.util.Base64.getDecoder().decode(decodedJWT.getPayload()));
		String header = new String(java.util.Base64.getDecoder().decode(decodedJWT.getHeader()));
		JSONObject jsonObject = JSONObject.parseObject(header);
		JSONObject payloadJsonObject = JSONObject.parseObject(payload);
		String data = payloadJsonObject.getString("data");
		JSONObject dataJsonObject = JSONObject.parseObject(data);
		String signedTransactionInfo = dataJsonObject.getString("signedTransactionInfo");
		DecodedJWT signedTransactionInfoJWT = JWT.decode(signedTransactionInfo);
		String signedPayload = new String(java.util.Base64.getDecoder().decode(signedTransactionInfoJWT.getPayload()));
		System.out.println("signedPayload===>" + signedPayload);
		JSONObject signedPayloadJsonObject = JSONObject.parseObject(signedPayload);
		String expiresDate = signedPayloadJsonObject.getString("expiresDate");
		LocalDateTime localDateTime = Instant.ofEpochMilli(Long.valueOf(expiresDate)).atZone(ZoneOffset.ofHours(8)).toLocalDateTime();
		System.out.println("过期时间为 ===>" + localDateTime.toString());
		// 获取公钥
		PublicKey publicKey = getPublicKeyByX5c(jsonObject.getJSONArray("x5c").get(0).toString());
		// 验证 token
		Algorithm algorithm = Algorithm.ECDSA256((ECPublicKey) publicKey, null);
		algorithm.verify(decodedJWT);
	}

	public static PublicKey getPublicKeyByX5c(String x5c) throws CertificateException {
		byte[] x5c0Bytes = java.util.Base64.getDecoder().decode(x5c);
		CertificateFactory fact = CertificateFactory.getInstance("X.509");
		X509Certificate cer = (X509Certificate) fact.generateCertificate(new ByteArrayInputStream(x5c0Bytes));
		return cer.getPublicKey();
	}


}
